package game.scenario;

import game.player.Player;
import game.towers.SimpleTower;
import game.towers.TowerMatrix;
import gui.GameButtonListener;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.Iterator;
import java.util.Vector;

import utils.DBG;
import utils.Properties;
import core.Camera;
import core.ImageLibrary;
import core.pathfinder.Pathfinder;
import core.rendering.RenderableMouse;

public class Map extends RenderableMouse implements GameButtonListener {

	public final static int NAVIGABLE = 0;
	public final static int TOGGLE_ROUTE_EDITING_MODE = 301;

	int[][] mapdata;
	ImageLibrary ilib;
	
	int xsel;
	int ysel;
	
	int width;
	int height;
	
	Wave wave;
	TowerMatrix towers;
	
	boolean editing_route = false;
	Point beginPoint;
	Point endPoint;
	
	Camera cam = Camera.getInstance();
	
	Vector<GraphicMapLayer> mapLayers;
	
	public Map(String map) {
		super();
		 
		mapdata = MapData.getMap(map);
		mapLayers = new Vector<GraphicMapLayer>();
		
		mapLayers.add(new GraphicMapLayer(mapdata , new MapTileset()));
		
		
		width = mapdata.length * Properties.TILE_WIDTH;
		height = mapdata[0].length * Properties.TILE_HEIGHT;
		//register this map to the pathfinder.
		Pathfinder.getInstance().setMap(this);
		
		towers = new TowerMatrix(mapdata.length, mapdata[0].length, 0, 0);
		ilib = ImageLibrary.getInstance();
		this.size = new Dimension(mapdata.length * Properties.TILE_WIDTH,
				mapdata[0].length * Properties.TILE_HEIGHT);
		
		
		beginPoint = new Point(0 , 0);
		endPoint = new Point(0 , 0);
		
		for (int cont = 0; cont < mapdata.length; cont++) {
			for (int cont2 = 0; cont2 < mapdata[cont].length; cont2++) {
				if (mapdata[cont][cont2] == -1) {
					beginPoint.x = cont;
					beginPoint.y = cont2;
				}
				if (mapdata[cont][cont2] == -2) {
					endPoint.x = cont;
					endPoint.y = cont2;
				}
			}
		}
		
		wave = new Wave(5 , this.getBeginPoint() , this.getEndPoint());
		wave.needsRecalculation = true;
	}
	
	public int getWidth(){
		return width;
	}
	
	public int getHeight(){
		return height;
	}
	
	public Point getBeginPoint(){
		return beginPoint;
	}
	
	public Point getEndPoint(){
		return endPoint;
	}

	@Override
	public void renderComponent(Graphics2D g2d) {
		// TODO Auto-generated method stub
		g2d.translate(this.getX() , this.getY() );
		
		Iterator<GraphicMapLayer> it = mapLayers.iterator();
		while(it.hasNext()){
			it.next().render(g2d);
		}
		if (towers.canAddTower(xsel, ysel)) {
			g2d.setColor(Color.green);
		} else {
			g2d.setColor(Color.red);
		}
		g2d.drawRect(xsel * Properties.TILE_WIDTH, ysel
				* Properties.TILE_HEIGHT,
				Properties.TILE_WIDTH - 1,
				Properties.TILE_HEIGHT - 1);
		
		wave.render(g2d);
		towers.render(g2d);
		g2d.translate(-(this.getX()), -(this.getY()));
	}

	@Override
	public synchronized boolean onClick(MouseEvent e) {
		// TODO Auto-generated method stub
		
			if (Player.getInstance().canPay(SimpleTower.getCost())) {
				Player.getInstance().substractCash(SimpleTower.getCost());
				if (this.getNavigationMatrix()[xsel][ysel] != false){
					towers.addTower(xsel, ysel);
					wave.needsRecalculation = true;
				}
			} else {
				DBG.showMsg("Player cant pay that" + SimpleTower.getCost()
						+ " His money is " + Player.getInstance().getCash(),
						this);
				return false;
			}
			return true;
	}

	@Override
	public void updateMouse(Point p) {
		// TODO Auto-generated method stub
		xsel = (int) (p.x - this.getX()) / Properties.TILE_WIDTH;
		ysel = (int) (p.y - this.getY()) / Properties.TILE_HEIGHT;
	}

	int wave_count = 0;
	int updateroute = 0;
	@Override
	public void updateLogic() {
		// TODO Auto-generated method stub
		towers.updateLogic();
		wave.updateLogic();
		
		if (wave.isEmpty()) {
			wave = new Wave(wave_count * 10, this.getBeginPoint() , this.getEndPoint());
			wave_count++;
			if (wave_count % 3 == 0) {
				Player.getInstance().increaseLevel();
			}
			wave.needsRecalculation = true;
			wave.updateLogic();
		}
		if (towers.getWave() != wave) {
			towers.setWave(wave);
		}
	}

	public boolean isNavigable(int nav_x, int nav_y) {
		return this.mapdata[nav_x][nav_y] == Map.NAVIGABLE;
	}

	public Point getPixelCoordinates(Point values) {
		return new Point(
				(values.x * Properties.TILE_WIDTH) + (int) this.getX(),
				(values.y * Properties.TILE_HEIGHT) + (int) this.getY());
	}

	@Override
	public boolean doAction(int actionCode) {
		boolean retorn = false;
		// TODO Auto-generated method stub
		switch (actionCode) {
		case Map.TOGGLE_ROUTE_EDITING_MODE:
			if (!editing_route) {
				editing_route = true;
				retorn = true;
			} else {
				editing_route = false;
				retorn = true;
			}
			break;
		}
		return retorn;
	}
	
	public boolean[][] getNavigationMatrix(){
		boolean [][] n = new boolean[mapdata.length][mapdata[0].length];
		
		for (int cont=0 ; cont< n.length ; cont++){
			for(int cont2 = 0 ; cont2 < n[0].length ; cont2++){
				n[cont][cont2] = false;
				n[cont][cont2] = towers.canAddTower(cont, cont2) && mapdata[cont][cont2] != 1;
			}
		}
		return n;
	}

}
